#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <cstdio>
#include <cstring>
#include <vector>

#include "LockGurad.hpp"

using namespace std;

#define NUM 4

int tickets = 1000;  //用多线程, 模拟一轮抢票

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

class threadData
{
public:
    threadData(int number/*,pthread_mutex_t *mutex*/)
    {
        threadname = "thread-" + to_string(number);
        //lock = mutex;
    }
public:
    string threadname;
    //pthread_mutex_t* lock;
};

//v1
// void* getTicket(void* args)
// {
//     threadData *td = static_cast<threadData*>(args);

//     const char* name = td->threadname.c_str();

//     while (true)
//     {
//         {
//             LockGuard lockgurad(&lock);     //临时的LockGurad对象

//             if (tickets > 0)
//             {
//                 usleep(1000);
//                 printf("who=%s, get a ticket: %d\n",name,tickets);  //临时的LockGurad对象,RALL风格
//                 tickets--;
//             }
//             else 
//             {
//                 break;
//             }
//         }
        
//         usleep(10);
//     }

//     printf("%s ... quit\n", name);

//     return nullptr;
// }

//v1
void* getTicket(void* args)
{
    threadData *td = static_cast<threadData*>(args);

    const char* name = td->threadname.c_str();

    while (true)
    {
        pthread_mutex_lock(&lock);
        if (tickets > 0)
        {
            usleep(1000);
            printf("who=%s, get a ticket: %d\n",name,tickets);  //
            tickets--;
            pthread_mutex_unlock(&lock);
        }
        else 
        {
            pthread_mutex_unlock(&lock);
            break;
        }

        //usleep(10);
    }

    printf("%s ... quit\n", name);

    return nullptr;
}

int main()
{
    //pthread_mutex_t lock;
    //pthread_mutex_init(&lock,nullptr);

    vector<pthread_t> tids;
    vector<threadData*> thread_datas;

    for (int i = 1; i <= NUM; i++)
    {
        pthread_t tid;
        threadData* td = new threadData(i/*,&lock*/);
        thread_datas.push_back(td);
        pthread_create(&tid,nullptr,getTicket,thread_datas[i-1]);
        tids.push_back(tid);
    }

    for (auto thread : tids)
    {
        pthread_join(thread,nullptr);
    }

    for (auto td : thread_datas)
    {
        delete td;
    }

    //pthread_mutex_destroy(&lock);

    return 0;
}

// #define NUM 3

// int* p = nullptr;

// __thread int g_val = 0;

// __thread pthread_t number = 0;
// __thread pid_t pid = 0;

// struct ThreadData
// {
//     string threadname;
// };

// string toHex(pthread_t tid)
// {
//     char buffer[64];
//     snprintf(buffer,sizeof(buffer),"%x",tid);

//     return buffer;
// }

// void* threadRoutine(void* args)
// {
//     pthread_detach(pthread_self());

//     ThreadData *td = static_cast<ThreadData*>(args);

//     int test_i = 0;

//     number = pthread_self();
//     pid = getpid();

//     if (td->threadname == "thread-2") p = &test_i;
 
//     int i = 0;
//     while (i < 10)
//     {
//         // cout << "pid: " << getpid() << ",tid : " << toHex(pthread_self()) 
//         // << " ,threadname: " << td->threadname << " ,test_i : " << test_i << " ,&test_i: " << &test_i << endl;
//         cout << "pid: " << pid << ",tid : " << toHex(number) 
//         << " ,threadname: " << td->threadname << " ,g_val : " << g_val << " ,&g_val : " << &g_val << endl;
//         i++;
//         test_i++;

//         g_val++;
//         sleep(1);
//     }

//     delete td;
//     return nullptr;
// }

// void InitThreadData(ThreadData* td,int number)
// {
//     td->threadname = "thread-" + to_string(number);
    
// }

// int main()
// {
//     vector<pthread_t> tids;
//     for (int i = 0; i < NUM; i++)
//     {
//         pthread_t tid;


//         ThreadData* td = new ThreadData;
//         InitThreadData(td,i);

//         pthread_create(&tid,nullptr,threadRoutine,td);
//         tids.push_back(tid);
//         //sleep(1);

//     }

//     sleep(1); //确保复制成功

//     //cout << "mian thread get a thread local value, val: " << *p << " ,&val: " << p << endl;

//     // for (auto i : tids)
//     // {
//     //     pthread_detach(i);
//     // }

//     for (int i = 0; i < NUM; i++)
//     {
//         int n = pthread_join(tids[i],nullptr);
//         printf("n = %d, who = %x, why: %s\n",n,tids[i],strerror(n));
//     }

//     return 0;
// }